home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1999 May
/
Macworld (1999-05).dmg
/
Updaters
/
SpriteWorld 2.2.1 Update
/
Source Updates
/
SpriteWorld.c
< prev
next >
Wrap
Text File
|
1999-03-02
|
68KB
|
2,307 lines
///--------------------------------------------------------------------------------------
// SpriteWorld.c
//
// Portions are copyright: © 1991-94 Tony Myles, All rights reserved worldwide.
//
// Description: implementation of the sprite world architecture
///--------------------------------------------------------------------------------------
#ifndef __SWCOMMON__
#include "SWCommonHeaders.h"
#endif
#ifndef __QUICKDRAW__
#include <QuickDraw.h>
#endif
#ifndef __MEMORY__
#include <Memory.h>
#endif
#ifndef __GESTALT__
#include <Gestalt.h>
#endif
#ifndef __TIMER__
#include <Timer.h>
#endif
#ifndef __SPRITEWORLDUTILS__
#include "SpriteWorldUtils.h"
#endif
#ifndef __SPRITEWORLD__
#include "SpriteWorld.h"
#endif
#ifndef __SPRITELAYER__
#include "SpriteLayer.h"
#endif
#ifndef __SPRITE__
#include "Sprite.h"
#endif
#ifndef __SPRITEFRAME__
#include "SpriteFrame.h"
#endif
#ifndef __BLITPIXIE__
#include "BlitPixie.h"
#endif
#ifndef __RETRACE__
#include <Retrace.h>
#endif
#ifndef __SCROLLING__
#include "Scrolling.h"
#endif
#ifndef __TILING__
#include "Tiling.h"
#endif
SInt8 gSWmmuMode;
short gProcessorType; //
RgnHandle gCollisionSectRgn = NULL; /// Initialized by SWEnterSpriteWorld
RgnHandle gCollisionSpareRgn = NULL; //
SpritePtr gCurrentSpriteBeingDrawn = NULL;
SpriteWorldPtr gCleanUpSpriteWorldP = NULL;
///--------------------------------------------------------------------------------------
// SWEnterSpriteWorld
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWEnterSpriteWorld(void)
{
OSErr err = noErr;
gSWmmuMode = GetMMUMode();
if ( !SWHasSystem7() )
{
err = kSystemTooOldErr;
}
SWGetProcessorType(&gProcessorType);
if (gCollisionSectRgn == NULL && gCollisionSpareRgn == NULL)
{
gCollisionSectRgn = NewRgn();
gCollisionSpareRgn = NewRgn();
}
else
{
err = kAlreadyCalledErr;
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWCreateSpriteWorld
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWCreateSpriteWorld(
GDHandle mainGDH,
SpriteWorldPtr *spriteWorldP,
FramePtr windowFrameP,
FramePtr backFrameP,
FramePtr workFrameP,
short maxDepth)
{
OSErr err;
SpriteWorldPtr tempSpriteWorldP;
PixMapHandle basePixMap;
err = noErr;
*spriteWorldP = NULL;
tempSpriteWorldP = (SpriteWorldPtr)NewPtrClear((Size)sizeof(SpriteWorldRec));
if (tempSpriteWorldP == NULL)
err = MemError();
if (err == noErr)
{
// Create the deadSpriteLayerP, but don't add it to the linked layer list
err = SWCreateSpriteLayer(&tempSpriteWorldP->deadSpriteLayerP);
if (err != noErr)
DisposePtr((Ptr)tempSpriteWorldP);
}
if (err == noErr)
{
basePixMap = (**mainGDH).gdPMap;
if ( maxDepth == 0 || (**basePixMap).pixelSize <= maxDepth )
{
tempSpriteWorldP->pixelDepth = (**basePixMap).pixelSize;
}
else
{
tempSpriteWorldP->pixelDepth = maxDepth;
}
tempSpriteWorldP->headSpriteLayerP = NULL;
tempSpriteWorldP->tailSpriteLayerP = NULL;
tempSpriteWorldP->mainSWGDH = mainGDH;
tempSpriteWorldP->windowFrameP = windowFrameP;
tempSpriteWorldP->extraBackFrameP = NULL;
tempSpriteWorldP->backFrameP = backFrameP;
tempSpriteWorldP->workFrameP = workFrameP;
tempSpriteWorldP->offscreenDrawProc = SWStdWorldDrawProc;
tempSpriteWorldP->screenDrawProc = SWStdWorldDrawProc;
tempSpriteWorldP->doubleRectDrawProc = NULL;
tempSpriteWorldP->postEraseCallBack = NULL;
tempSpriteWorldP->postDrawCallBack = NULL;
tempSpriteWorldP->windRect = windowFrameP->frameRect;
tempSpriteWorldP->backRect = backFrameP->frameRect;
tempSpriteWorldP->originalWindRect = windowFrameP->frameRect;
tempSpriteWorldP->originalBackRect = backFrameP->frameRect;
tempSpriteWorldP->headUpdateRectP = NULL;
tempSpriteWorldP->scrollRectMoveBounds.left = 0;
tempSpriteWorldP->scrollRectMoveBounds.top = 0;
tempSpriteWorldP->scrollRectMoveBounds.right = 32767;
tempSpriteWorldP->scrollRectMoveBounds.bottom = 32767;
tempSpriteWorldP->horizScrollRectOffset = 0;
tempSpriteWorldP->vertScrollRectOffset = 0;
tempSpriteWorldP->horizScrollDelta = 0;
tempSpriteWorldP->vertScrollDelta = 0;
tempSpriteWorldP->worldMoveProc = NULL;
// Make sure visScrollRect is at 0,0 top-left corner
tempSpriteWorldP->visScrollRect = windowFrameP->frameRect;
OffsetRect(&tempSpriteWorldP->visScrollRect,
-tempSpriteWorldP->visScrollRect.left,
-tempSpriteWorldP->visScrollRect.top);
tempSpriteWorldP->offscreenScrollRect = tempSpriteWorldP->visScrollRect;
tempSpriteWorldP->oldVisScrollRect = tempSpriteWorldP->visScrollRect;
tempSpriteWorldP->tileLayerArray = NULL;
tempSpriteWorldP->tilingCache = NULL;
tempSpriteWorldP->changedTiles = NULL;
tempSpriteWorldP->tilingIsInitialized = false;
tempSpriteWorldP->tilingIsOn = false;
tempSpriteWorldP->numTilesChanged = 0;
tempSpriteWorldP->tileChangeProc = NULL;
tempSpriteWorldP->tileRectDrawProc = SWDrawTilesInRect;
tempSpriteWorldP->tileMaskDrawProc = SWStdSpriteDrawProc;
tempSpriteWorldP->partialMaskDrawProc = SWStdSpriteDrawProc;
tempSpriteWorldP->frameHasOccurred = false;
tempSpriteWorldP->fpsTimeInterval = 0L;
tempSpriteWorldP->lastMicroseconds.hi = 0L;
tempSpriteWorldP->lastMicroseconds.lo = 0L;
tempSpriteWorldP->runningTimeCount = 0L;
tempSpriteWorldP->vblTaskRec.hasVBLFired = true;
tempSpriteWorldP->usingVBL = false;
SWClearStickyError();
*spriteWorldP = tempSpriteWorldP;
}
return err;
}
///--------------------------------------------------------------------------------------
// SWCreateSpriteWorldFromWindow
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWCreateSpriteWorldFromWindow(
SpriteWorldPtr* spriteWorldP,
CWindowPtr srcWindowP,
Rect* worldRectP,
Rect* offscreenRectP,
short maxDepth)
{
OSErr err = noErr;
FramePtr windowFrameP, backFrameP, workFrameP;
Rect tempRect, globalRect, windRect;
GDHandle mainGDH;
PixMapHandle basePixMap;
short depth;
*spriteWorldP = NULL;
windowFrameP = backFrameP = workFrameP = NULL;
SetPort( (WindowPtr)srcWindowP );
windRect = (worldRectP == NULL) ? srcWindowP->portRect : *worldRectP;
globalRect = windRect;
LocalToGlobal((Point *)&globalRect.top);
LocalToGlobal((Point *)&globalRect.bottom);
mainGDH = GetMaxDevice( &globalRect );
SetGDevice( mainGDH );
basePixMap = (**mainGDH).gdPMap;
if ( maxDepth == 0 || (**basePixMap).pixelSize <= maxDepth )
{
depth = (**basePixMap).pixelSize;
}
else
{
depth = maxDepth;
}
if ( srcWindowP->portVersion < (short)0xC000 )
{
err = kNotCWindowErr;
}
// If a custom offscreenRect has been requested, use it instead.
if (offscreenRectP == NULL)
tempRect = windRect;
else
tempRect = *offscreenRectP;
// offset Rect to (0,0) for back and work frames
OffsetRect(&tempRect, -tempRect.left, -tempRect.top);
if (err == noErr)
{
// create window frame
err = SWCreateWindowFrame(&windowFrameP, &windRect, tempRect.bottom);
}
if (err == noErr)
{
// create back drop frame
err = SWCreateFrame(mainGDH, &backFrameP, &tempRect, depth);
}
if (err == noErr)
{
// create work frame
err = SWCreateFrame(mainGDH, &workFrameP, &tempRect, depth);
}
if (err == noErr)
{
// create sprite world
err = SWCreateSpriteWorld(mainGDH, spriteWorldP, windowFrameP,
backFrameP, workFrameP, maxDepth);
}
if (err != noErr)
{
// an error occurred so dispose of anything we managed to create
if (windowFrameP != NULL)
{
SWDisposeWindowFrame(&windowFrameP);
}
if (backFrameP != NULL)
{
SWDisposeFrame(&backFrameP);
}
if (workFrameP != NULL)
{
SWDisposeFrame(&workFrameP);
}
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWDisposeSpriteWorld
///--------------------------------------------------------------------------------------
SW_FUNC void SWDisposeSpriteWorld(
SpriteWorldPtr *spriteWorldPP)
{
SpriteWorldPtr spriteWorldP = *spriteWorldPP;
SpriteLayerPtr curLayerP;
SpritePtr curSpriteP;
if (spriteWorldP != NULL)
{
SWUnlockSpriteWorld(spriteWorldP);
while ((curLayerP = SWGetNextSpriteLayer(spriteWorldP, NULL)) != NULL)
{
// dispose of each sprite in the layer
while ((curSpriteP = SWGetNextSprite(curLayerP, NULL)) != NULL)
{
SWRemoveSprite(curSpriteP);
SWDisposeSprite(&curSpriteP);
}
// dispose of each layer in the spriteWorld
SWRemoveSpriteLayer(spriteWorldP, curLayerP);
SWDisposeSpriteLayer(&curLayerP);
}
SWDisposeAllSpritesInLayer(spriteWorldP->deadSpriteLayerP);
SWDisposeSpriteLayer(&spriteWorldP->deadSpriteLayerP);
SWDisposeFrame(&spriteWorldP->backFrameP);
SWDisposeFrame(&spriteWorldP->workFrameP);
SWDisposeFrame(&spriteWorldP->extraBackFrameP);
SWDisposeWindowFrame(&spriteWorldP->windowFrameP);
SWExitTiling(spriteWorldP);
SWSyncSpriteWorldToVBL(spriteWorldP, false);
DisposePtr((Ptr)spriteWorldP);
*spriteWorldPP = NULL; // Set original pointer to NULL
}
}
///--------------------------------------------------------------------------------------
// SWExitSpriteWorld
///--------------------------------------------------------------------------------------
SW_FUNC void SWExitSpriteWorld(void)
{
if (gCollisionSectRgn != NULL)
DisposeRgn(gCollisionSectRgn);
if (gCollisionSpareRgn != NULL)
DisposeRgn(gCollisionSpareRgn);
gCollisionSectRgn = NULL;
gCollisionSpareRgn = NULL;
}
///--------------------------------------------------------------------------------------
// SWAddSpriteLayer
///--------------------------------------------------------------------------------------
SW_FUNC void SWAddSpriteLayer(
SpriteWorldPtr spriteWorldP,
SpriteLayerPtr newSpriteLayerP)
{
SpriteLayerPtr tailSpriteLayerP = spriteWorldP->tailSpriteLayerP;
SW_ASSERT(spriteWorldP != NULL);
if (tailSpriteLayerP != NULL)
tailSpriteLayerP->nextSpriteLayerP = newSpriteLayerP;
else
spriteWorldP->headSpriteLayerP = newSpriteLayerP;
newSpriteLayerP->prevSpriteLayerP = tailSpriteLayerP;
newSpriteLayerP->nextSpriteLayerP = NULL;
// make the new layer the tail
spriteWorldP->tailSpriteLayerP = newSpriteLayerP;
}
///--------------------------------------------------------------------------------------
// SWRemoveSpriteLayer
///--------------------------------------------------------------------------------------
SW_FUNC void SWRemoveSpriteLayer(
SpriteWorldPtr spriteWorldP,
SpriteLayerPtr oldSpriteLayerP)
{
SW_ASSERT(spriteWorldP != NULL);
// is there a next layer?
if (oldSpriteLayerP->nextSpriteLayerP != NULL)
{
// link the next layer to the prev layer
oldSpriteLayerP->nextSpriteLayerP->prevSpriteLayerP = oldSpriteLayerP->prevSpriteLayerP;
}
else
{
// make the prev layer the tail
spriteWorldP->tailSpriteLayerP = oldSpriteLayerP->prevSpriteLayerP;
}
// is there a prev layer?
if (oldSpriteLayerP->prevSpriteLayerP != NULL)
{
// link the prev layer to the next layer
oldSpriteLayerP->prevSpriteLayerP->nextSpriteLayerP = oldSpriteLayerP->nextSpriteLayerP;
}
else
{
// make the next layer the head
spriteWorldP->headSpriteLayerP = oldSpriteLayerP->nextSpriteLayerP;
}
}
///--------------------------------------------------------------------------------------
// SWSwapSpriteLayer
///--------------------------------------------------------------------------------------
SW_FUNC void SWSwapSpriteLayer(
SpriteWorldPtr spriteWorldP,
SpriteLayerPtr srcSpriteLayerP,
SpriteLayerPtr dstSpriteLayerP)
{
register SpriteLayerPtr swapSpriteLayerP;
SW_ASSERT(spriteWorldP != NULL);
// adjacent Layers are a special case
if ( srcSpriteLayerP->nextSpriteLayerP == dstSpriteLayerP ||
dstSpriteLayerP->nextSpriteLayerP == srcSpriteLayerP )
{
if ( srcSpriteLayerP->nextSpriteLayerP == dstSpriteLayerP )
{
if ( srcSpriteLayerP->prevSpriteLayerP != NULL )
(srcSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP = dstSpriteLayerP;
if ( dstSpriteLayerP->nextSpriteLayerP != NULL )
(dstSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP = srcSpriteLayerP;
dstSpriteLayerP->prevSpriteLayerP = srcSpriteLayerP->prevSpriteLayerP;
srcSpriteLayerP->nextSpriteLayerP = dstSpriteLayerP->nextSpriteLayerP;
dstSpriteLayerP->nextSpriteLayerP = srcSpriteLayerP;
srcSpriteLayerP->prevSpriteLayerP = dstSpriteLayerP;
}
else
{
if ( dstSpriteLayerP->prevSpriteLayerP != NULL )
(dstSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP = srcSpriteLayerP;
if ( srcSpriteLayerP->nextSpriteLayerP != NULL )
(srcSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP = dstSpriteLayerP;
srcSpriteLayerP->prevSpriteLayerP = dstSpriteLayerP->prevSpriteLayerP;
dstSpriteLayerP->nextSpriteLayerP = srcSpriteLayerP->nextSpriteLayerP;
srcSpriteLayerP->nextSpriteLayerP = dstSpriteLayerP;
dstSpriteLayerP->prevSpriteLayerP = srcSpriteLayerP;
}
}
else
{
if ( srcSpriteLayerP->prevSpriteLayerP != NULL &&
dstSpriteLayerP->prevSpriteLayerP != NULL )
{
swapSpriteLayerP = (srcSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP;
(srcSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP =
(dstSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP;
(dstSpriteLayerP->prevSpriteLayerP)->nextSpriteLayerP = swapSpriteLayerP;
}
if ( srcSpriteLayerP->nextSpriteLayerP != NULL &&
dstSpriteLayerP->nextSpriteLayerP != NULL )
{
swapSpriteLayerP = (srcSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP;
(srcSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP =
(dstSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP;
(dstSpriteLayerP->nextSpriteLayerP)->prevSpriteLayerP = swapSpriteLayerP;
}
swapSpriteLayerP = srcSpriteLayerP->nextSpriteLayerP;
srcSpriteLayerP->nextSpriteLayerP = dstSpriteLayerP->nextSpriteLayerP;
dstSpriteLayerP->nextSpriteLayerP = swapSpriteLayerP;
swapSpriteLayerP = srcSpriteLayerP->prevSpriteLayerP;
srcSpriteLayerP->prevSpriteLayerP = dstSpriteLayerP->prevSpriteLayerP;
dstSpriteLayerP->prevSpriteLayerP = swapSpriteLayerP;
}
if (srcSpriteLayerP->nextSpriteLayerP == NULL)
{
spriteWorldP->tailSpriteLayerP = srcSpriteLayerP;
}
else if (srcSpriteLayerP->prevSpriteLayerP == NULL)
{
spriteWorldP->headSpriteLayerP = srcSpriteLayerP;
}
if (dstSpriteLayerP->nextSpriteLayerP == NULL)
{
spriteWorldP->tailSpriteLayerP = dstSpriteLayerP;
}
else if (dstSpriteLayerP->prevSpriteLayerP == NULL)
{
spriteWorldP->headSpriteLayerP = dstSpriteLayerP;
}
}
///--------------------------------------------------------------------------------------
// SWGetNextSpriteLayer
///--------------------------------------------------------------------------------------
SW_FUNC SpriteLayerPtr SWGetNextSpriteLayer(
SpriteWorldPtr spriteWorldP,
SpriteLayerPtr curSpriteLayerP)
{
SW_ASSERT(spriteWorldP != NULL);
return (curSpriteLayerP == NULL) ?
spriteWorldP->headSpriteLayerP :
curSpriteLayerP->nextSpriteLayerP;
}
///--------------------------------------------------------------------------------------
// SWLockSpriteWorld
///--------------------------------------------------------------------------------------
SW_FUNC void SWLockSpriteWorld(
SpriteWorldPtr spriteWorldP)
{
SpriteLayerPtr curSpriteLayerP;
SW_ASSERT(spriteWorldP != NULL);
SWLockWindowFrame(spriteWorldP->windowFrameP);
SWLockFrame(spriteWorldP->workFrameP);
SWLockFrame(spriteWorldP->backFrameP);
if (spriteWorldP->extraBackFrameP != NULL)
SWLockFrame(spriteWorldP->extraBackFrameP);
SWLockTiles(spriteWorldP);
curSpriteLayerP = spriteWorldP->headSpriteLayerP;
while (curSpriteLayerP != NULL)
{
SWLockSpriteLayer(curSpriteLayerP);
curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
}
}
///--------------------------------------------------------------------------------------
// SWUnlockSpriteWorld
///--------------------------------------------------------------------------------------
SW_FUNC void SWUnlockSpriteWorld(
SpriteWorldPtr spriteWorldP)
{
SpriteLayerPtr curSpriteLayerP;
SW_ASSERT(spriteWorldP != NULL);
SWUnlockWindowFrame(spriteWorldP->windowFrameP);
SWUnlockFrame(spriteWorldP->backFrameP);
SWUnlockFrame(spriteWorldP->workFrameP);
if (spriteWorldP->extraBackFrameP != NULL)
SWUnlockFrame(spriteWorldP->extraBackFrameP);
SWUnlockTiles(spriteWorldP);
curSpriteLayerP = spriteWorldP->headSpriteLayerP;
while (curSpriteLayerP != NULL)
{
SWUnlockSpriteLayer(curSpriteLayerP);
curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
}
}
#pragma mark -
///--------------------------------------------------------------------------------------
// SWSetPortToBackground
///--------------------------------------------------------------------------------------
SW_FUNC void SWSetPortToBackground(
SpriteWorldPtr spriteWorldP)
{
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
if ( spriteWorldP->backFrameP->isFrameLocked )
SetGWorld(spriteWorldP->backFrameP->framePort, nil);
}
///--------------------------------------------------------------------------------------
// SWSetPortToWorkArea
///--------------------------------------------------------------------------------------
SW_FUNC void SWSetPortToWorkArea(
SpriteWorldPtr spriteWorldP)
{
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
if ( spriteWorldP->workFrameP->isFrameLocked )
SetGWorld(spriteWorldP->workFrameP->framePort, nil);
}
///--------------------------------------------------------------------------------------
// SWSetPortToWindow
///--------------------------------------------------------------------------------------
SW_FUNC void SWSetPortToWindow(
SpriteWorldPtr spriteWorldP)
{
SW_ASSERT(spriteWorldP != NULL);
SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
}
///--------------------------------------------------------------------------------------
// SWSetSpriteWorldOffscreenDrawProc
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWSetSpriteWorldOffscreenDrawProc(
SpriteWorldPtr spriteWorldP,
DrawProcPtr drawProc)
{
OSErr err = noErr;
SW_ASSERT(spriteWorldP != NULL);
if (spriteWorldP->pixelDepth != 8)
{
if ( drawProc == BlitPixie8BitRectDrawProc ||
drawProc == BP8BitInterlacedRectDrawProc )
err = kWrongDepthErr;
}
if ( err == noErr )
spriteWorldP->offscreenDrawProc = drawProc;
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWSetSpriteWorldScreenDrawProc
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWSetSpriteWorldScreenDrawProc(
SpriteWorldPtr spriteWorldP,
DrawProcPtr drawProc)
{
OSErr err = noErr;
SW_ASSERT(spriteWorldP != NULL);
if (drawProc == NULL)
err = kNilParameterErr;
if ( (*spriteWorldP->windowFrameP->framePort->portPixMap)->pixelSize != 8 ||
(*spriteWorldP->windowFrameP->framePort->portPixMap)->pixelSize !=
spriteWorldP->pixelDepth )
{
if ( drawProc == BlitPixie8BitRectDrawProc ||
drawProc == BP8BitInterlacedRectDrawProc )
err = kWrongDepthErr;
}
if ( err == noErr )
spriteWorldP->screenDrawProc = drawProc;
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWSetPostEraseCallBack
///--------------------------------------------------------------------------------------
SW_FUNC void SWSetPostEraseCallBack(
SpriteWorldPtr spriteWorldP,
CallBackPtr callBack)
{
spriteWorldP->postEraseCallBack = callBack;
}
///--------------------------------------------------------------------------------------
// SWSetPostDrawCallBack
///--------------------------------------------------------------------------------------
SW_FUNC void SWSetPostDrawCallBack(
SpriteWorldPtr spriteWorldP,
CallBackPtr callBack)
{
spriteWorldP->postDrawCallBack = callBack;
}
///--------------------------------------------------------------------------------------
// SWStdWorldDrawProc
///--------------------------------------------------------------------------------------
SW_FUNC void SWStdWorldDrawProc(
FramePtr srcFrameP,
FramePtr dstFrameP,
Rect* srcRect,
Rect* dstRect)
{
Rect srcCopyBitsRect = *srcRect;
Rect dstCopyBitsRect = *dstRect;
// clip off the top
if (dstCopyBitsRect.top < dstFrameP->frameRect.top)
{
srcCopyBitsRect.top += dstFrameP->frameRect.top - dstCopyBitsRect.top;
dstCopyBitsRect.top = dstFrameP->frameRect.top;
if (dstCopyBitsRect.top >= dstCopyBitsRect.bottom) return;
}
// clip off the bottom
if (dstCopyBitsRect.bottom > dstFrameP->frameRect.bottom)
{
srcCopyBitsRect.bottom -= dstCopyBitsRect.bottom - dstFrameP->frameRect.bottom;
dstCopyBitsRect.bottom = dstFrameP->frameRect.bottom;
if (dstCopyBitsRect.bottom <= dstCopyBitsRect.top) return;
}
// clip off the left
if (dstCopyBitsRect.left < dstFrameP->frameRect.left)
{
srcCopyBitsRect.left += dstFrameP->frameRect.left - dstCopyBitsRect.left;
dstCopyBitsRect.left = dstFrameP->frameRect.left;
if (dstCopyBitsRect.left >= dstCopyBitsRect.right)
return;
}
// clip off the right
if (dstCopyBitsRect.right > dstFrameP->frameRect.right)
{
srcCopyBitsRect.right -= dstCopyBitsRect.right - dstFrameP->frameRect.right;
dstCopyBitsRect.right = dstFrameP->frameRect.right;
if (dstCopyBitsRect.right <= dstCopyBitsRect.left) return;
}
CopyBits( (BitMap*)srcFrameP->framePix,
(BitMap*)dstFrameP->framePix,
&srcCopyBitsRect,
&dstCopyBitsRect,
srcCopy, NULL);
}
///--------------------------------------------------------------------------------------
// SWCopyBackgroundToWorkArea
///--------------------------------------------------------------------------------------
SW_FUNC void SWCopyBackgroundToWorkArea(
SpriteWorldPtr spriteWorldP)
{
GWorldPtr holdGWorld;
GDHandle holdGDH;
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
GetGWorld( &holdGWorld, &holdGDH );
// Copy the background frame into the work area
SetGWorld(spriteWorldP->workFrameP->framePort, nil);
(*spriteWorldP->offscreenDrawProc)(spriteWorldP->backFrameP,
spriteWorldP->workFrameP,
&spriteWorldP->backFrameP->frameRect,
&spriteWorldP->workFrameP->frameRect);
SetGWorld( holdGWorld, holdGDH );
}
///--------------------------------------------------------------------------------------
// SWChangeWorldRect
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWChangeWorldRect(
SpriteWorldPtr spriteWorldP,
Rect* newWorldRectP,
Boolean changeOffscreenAreas)
{
Rect oldWindRect;
short hChange, vChange;
OSErr err = noErr;
SW_ASSERT(spriteWorldP != NULL && newWorldRectP != NULL);
// Report error if newWorldRectP is larger than the size of the offscreen areas
if ( SW_RECT_WIDTH((*newWorldRectP)) > SW_RECT_WIDTH(spriteWorldP->originalBackRect) ||
SW_RECT_HEIGHT((*newWorldRectP)) > SW_RECT_HEIGHT(spriteWorldP->originalBackRect) )
{
err = kOutOfRangeErr;
}
if (err == noErr)
{
// Now we calculate the difference in size of old and new windRect
oldWindRect = spriteWorldP->windRect;
hChange = (oldWindRect.right - oldWindRect.left) -
(newWorldRectP->right - newWorldRectP->left);
vChange = (oldWindRect.bottom - oldWindRect.top) -
(newWorldRectP->bottom - newWorldRectP->top);
// Change the windRect
spriteWorldP->windRect = *newWorldRectP;
// Resize the visScrollRect
SWResizeVisScrollRect(spriteWorldP,
newWorldRectP->right - newWorldRectP->left,
newWorldRectP->bottom - newWorldRectP->top);
if (changeOffscreenAreas)
{
// Make offscreen areas think they are the same size as the new windRect
spriteWorldP->workFrameP->frameRect.bottom -= vChange;
spriteWorldP->workFrameP->frameRect.right -= hChange;
spriteWorldP->backFrameP->frameRect.bottom -= vChange;
spriteWorldP->backFrameP->frameRect.right -= hChange;
// Update backRect as well
spriteWorldP->backRect.bottom -= vChange;
spriteWorldP->backRect.right -= hChange;
}
// Recalculate blitter data based on new windRect position
SWWindowMoved(spriteWorldP);
}
return err;
}
///--------------------------------------------------------------------------------------
// SWRestoreWorldRect
///--------------------------------------------------------------------------------------
SW_FUNC void SWRestoreWorldRect(SpriteWorldPtr spriteWorldP)
{
Rect originalWindRect = spriteWorldP->originalWindRect;
SW_ASSERT(spriteWorldP != NULL);
// Restore everything to its original size
spriteWorldP->windRect = originalWindRect;
spriteWorldP->workFrameP->frameRect = spriteWorldP->originalBackRect;
spriteWorldP->backFrameP->frameRect = spriteWorldP->originalBackRect;
spriteWorldP->backRect = spriteWorldP->originalBackRect;
// Resize the visScrollRect to match the originalWindRect
SWResizeVisScrollRect(spriteWorldP,
originalWindRect.right - originalWindRect.left,
originalWindRect.bottom - originalWindRect.top);
// Recalculate blitter data based on new windRect position
SWWindowMoved(spriteWorldP);
}
///--------------------------------------------------------------------------------------
// SWWindowMoved
///--------------------------------------------------------------------------------------
SW_FUNC void SWWindowMoved(SpriteWorldPtr spriteWorldP)
{
GDHandle theGDH,
holdGDH;
GWorldPtr holdGWorld;
Rect worldRect,
globalWorldRect,
screenRect;
short depth;
long curScanLine;
Point globalOffset;
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
GetGWorld( &holdGWorld, &holdGDH );
SWSetPortToWindow( spriteWorldP );
theGDH = spriteWorldP->mainSWGDH;
worldRect = spriteWorldP->windRect;
globalWorldRect = worldRect;
screenRect = (*theGDH)->gdRect;
LocalToGlobal( &(topLeft(globalWorldRect)) );
LocalToGlobal( &(botRight(globalWorldRect)) );
globalOffset = topLeft(globalWorldRect);
// Clip worldRect with screenRect
if (globalWorldRect.top < screenRect.top)
globalWorldRect.top = screenRect.top;
if (globalWorldRect.bottom > screenRect.bottom)
globalWorldRect.bottom = screenRect.bottom;
if (globalWorldRect.left < screenRect.left)
globalWorldRect.left = screenRect.left;
if (globalWorldRect.right > screenRect.right)
globalWorldRect.right = screenRect.right;
// Convert global rect back to local rect
GlobalToLocal( &(topLeft(globalWorldRect)) );
GlobalToLocal( &(botRight(globalWorldRect)) );
spriteWorldP->windowFrameP->frameRect = globalWorldRect;
// cache frameRowBytes for use by our blitter routine
spriteWorldP->windowFrameP->frameRowBytes =
(**spriteWorldP->windowFrameP->framePort->portPixMap).rowBytes & 0x7FFF;
depth = (**(**theGDH).gdPMap).pixelSize;
// align on long word boundary
spriteWorldP->windowFrameP->rightAlignFactor =
((sizeof(long) * kBitsPerByte) / depth) - 1;
spriteWorldP->windowFrameP->leftAlignFactor =
~(spriteWorldP->windowFrameP->rightAlignFactor);
// set the worldRectOffset
spriteWorldP->windowFrameP->worldRectOffset = 0;
if (depth < 8)
{
short roundOff;
roundOff = 8/depth;
spriteWorldP->windowFrameP->worldRectOffset =
(globalOffset.h - worldRect.left) -
(((globalOffset.h - worldRect.left)/roundOff)*roundOff);
}
// set up an array of offsets to the scan lines
for (curScanLine = 0; curScanLine < spriteWorldP->windowFrameP->numScanLines; curScanLine++)
{
spriteWorldP->windowFrameP->scanLinePtrArray[curScanLine] =
((curScanLine+(globalOffset.v - worldRect.top) ) *
spriteWorldP->windowFrameP->frameRowBytes) +
(globalOffset.h - worldRect.left)*4/(32/depth);
}
SetGWorld( holdGWorld, holdGDH );
}
///--------------------------------------------------------------------------------------
// SWWindowFrameMoved
///--------------------------------------------------------------------------------------
SW_FUNC void SWWindowFrameMoved(
FramePtr windowFrameP,
Rect *frameRect)
{
GDHandle theGDH,
holdGDH;
GWorldPtr theGWorld,
holdGWorld;
Rect worldRect,
globalWorldRect,
screenRect;
short depth;
long curScanLine;
Point globalOffset;
SW_ASSERT(windowFrameP != NULL);
SW_ASSERT(windowFrameP->isFrameLocked);
GetGWorld( &holdGWorld, &holdGDH );
SetGWorld(windowFrameP->framePort, nil);
GetGWorld(&theGWorld, &theGDH); // Get the GDH
worldRect = *frameRect;
globalWorldRect = *frameRect;
screenRect = (*theGDH)->gdRect;
LocalToGlobal( &(topLeft(globalWorldRect)) );
LocalToGlobal( &(botRight(globalWorldRect)) );
globalOffset = topLeft(globalWorldRect);
// Clip worldRect with screenRect
if (globalWorldRect.top < screenRect.top)
globalWorldRect.top = screenRect.top;
if (globalWorldRect.bottom > screenRect.bottom)
globalWorldRect.bottom = screenRect.bottom;
if (globalWorldRect.left < screenRect.left)
globalWorldRect.left = screenRect.left;
if (globalWorldRect.right > screenRect.right)
globalWorldRect.right = screenRect.right;
// Convert global rect back to local rect
GlobalToLocal( &(topLeft(globalWorldRect)) );
GlobalToLocal( &(botRight(globalWorldRect)) );
windowFrameP->frameRect = globalWorldRect;
// cache frameRowBytes for use by our blitter routine
windowFrameP->frameRowBytes = (**windowFrameP->framePort->portPixMap).rowBytes & 0x7FFF;
depth = (**(**theGDH).gdPMap).pixelSize;
// align to long boundary
windowFrameP->rightAlignFactor = ((sizeof(long) * kBitsPerByte) / depth) - 1;
windowFrameP->leftAlignFactor = ~(windowFrameP->rightAlignFactor);
// set the worldRectOffset
windowFrameP->worldRectOffset = 0;
if (depth < 8)
{
short roundOff;
roundOff = 8/depth;
windowFrameP->worldRectOffset = (globalOffset.h - worldRect.left) -
(((globalOffset.h - worldRect.left)/roundOff)*roundOff);
}
// set up an array of offsets to the scan lines
for (curScanLine = 0; curScanLine < windowFrameP->numScanLines; curScanLine++)
{
windowFrameP->scanLinePtrArray[curScanLine] =
((curScanLine+(globalOffset.v - worldRect.top) ) *
windowFrameP->frameRowBytes) + (globalOffset.h - worldRect.left)*4/(32/depth);
}
SetGWorld( holdGWorld, holdGDH );
}
///--------------------------------------------------------------------------------------
// SWUpdateWindow
///--------------------------------------------------------------------------------------
SW_FUNC void SWUpdateWindow(
SpriteWorldPtr spriteWorldP)
{
GWorldPtr holdGWorld;
GDHandle holdGDH;
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
GetGWorld( &holdGWorld, &holdGDH );
SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
spriteWorldP->numTilesChanged = 0;
if ( spriteWorldP->usingVBL )
{
spriteWorldP->vblTaskRec.hasVBLFired = false;
while ( !spriteWorldP->vblTaskRec.hasVBLFired )
{}
}
(*spriteWorldP->screenDrawProc)(spriteWorldP->workFrameP,
spriteWorldP->windowFrameP,
&spriteWorldP->visScrollRect,
&spriteWorldP->windowFrameP->frameRect);
SetGWorld( holdGWorld, holdGDH );
}
#pragma mark -
///--------------------------------------------------------------------------------------
// SWUpdateSpriteWorld
///--------------------------------------------------------------------------------------
SW_FUNC void SWUpdateSpriteWorld(
SpriteWorldPtr spriteWorldP,
Boolean updateWindow)
{
UpdateRectStructPtr curRectStructP,
nextRectStructP;
register SpriteLayerPtr curSpriteLayerP;
register SpritePtr curSpriteP;
Rect tempRect;
GWorldPtr holdGWorld;
GDHandle holdGDH;
short curTileLayer;
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
GetGWorld( &holdGWorld, &holdGDH );
// Copy the background into the work area
SetGWorld(spriteWorldP->workFrameP->framePort, nil);
(*spriteWorldP->offscreenDrawProc)(spriteWorldP->backFrameP,
spriteWorldP->workFrameP,
&spriteWorldP->backFrameP->frameRect,
&spriteWorldP->workFrameP->frameRect);
// Call the postEraseCallBack
if (spriteWorldP->postEraseCallBack != NULL)
(*spriteWorldP->postEraseCallBack)(spriteWorldP);
// Build the current frame of the animation in the work area
curSpriteLayerP = spriteWorldP->headSpriteLayerP;
curTileLayer = 0;
// iterate through the layers in this world
while (curSpriteLayerP != NULL)
{
curSpriteP = curSpriteLayerP->headSpriteP;
if (curSpriteLayerP->tileLayer > curTileLayer)
curTileLayer = curSpriteLayerP->tileLayer;
// iterate through the sprites in this layer
while (curSpriteP != NULL)
{
SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
curSpriteP->tileDepth = curTileLayer;
if (curSpriteP->isVisible)
{
gCurrentSpriteBeingDrawn = curSpriteP;
// draw the sprite in the work area
(*curSpriteP->frameDrawProc)(curSpriteP->curFrameP,
spriteWorldP->workFrameP,
&curSpriteP->curFrameP->frameRect,
&curSpriteP->destFrameRect);
gCurrentSpriteBeingDrawn = NULL;
if (spriteWorldP->tilingIsOn &&
curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
{
tempRect = curSpriteP->destFrameRect;
// Clip tempRect to visScrollRect
if (tempRect.left < spriteWorldP->visScrollRect.left)
tempRect.left = spriteWorldP->visScrollRect.left;
if (tempRect.right > spriteWorldP->visScrollRect.right)
tempRect.right = spriteWorldP->visScrollRect.right;
if (tempRect.top < spriteWorldP->visScrollRect.top)
tempRect.top = spriteWorldP->visScrollRect.top;
if (tempRect.bottom > spriteWorldP->visScrollRect.bottom)
tempRect.bottom = spriteWorldP->visScrollRect.bottom;
SWDrawTilesAboveSprite(spriteWorldP, &tempRect, curSpriteP->tileDepth);
}
}
// set the delta and last rect to the current rect
curSpriteP->deltaFrameRect = curSpriteP->destFrameRect;
curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
// this sprite no longer needs to be drawn
curSpriteP->needsToBeDrawn = false;
curSpriteP->needsToBeErased = false;
curSpriteP = curSpriteP->nextSpriteP;
}
curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
}
// Call the postDrawCallBack
if (spriteWorldP->postDrawCallBack != NULL)
(*spriteWorldP->postDrawCallBack)(spriteWorldP);
// Copy the work area into the window
if (updateWindow)
{
SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
if ( spriteWorldP->usingVBL )
{
spriteWorldP->vblTaskRec.hasVBLFired = false;
while ( !spriteWorldP->vblTaskRec.hasVBLFired )
{}
}
(*spriteWorldP->screenDrawProc)(spriteWorldP->workFrameP,
spriteWorldP->windowFrameP,
&spriteWorldP->visScrollRect,
&spriteWorldP->windowFrameP->frameRect);
}
// dispose of flagged background rects
nextRectStructP = spriteWorldP->headUpdateRectP;
while ( nextRectStructP != NULL )
{
curRectStructP = nextRectStructP;
nextRectStructP = curRectStructP->nextRectStructP;
DisposePtr( (Ptr)curRectStructP );
}
spriteWorldP->headUpdateRectP = NULL;
spriteWorldP->numTilesChanged = 0;
SetGWorld( holdGWorld, holdGDH );
}
///--------------------------------------------------------------------------------------
// SWProcessSpriteWorld
///--------------------------------------------------------------------------------------
SW_FUNC void SWProcessSpriteWorld(
SpriteWorldPtr spriteWorldP)
{
UnsignedWide curMicroseconds;
register unsigned long millisecDifference;
register SpriteLayerPtr curSpriteLayerP;
register SpritePtr curSpriteP, nextSpriteP;
register FramePtr newFrameP;
SW_ASSERT(spriteWorldP != NULL);
Microseconds( &curMicroseconds );
// has hi long has rolled over?
if ( curMicroseconds.hi > spriteWorldP->lastMicroseconds.hi )
{
millisecDifference =
(0xffffffff - (spriteWorldP->lastMicroseconds.lo - curMicroseconds.lo))/1000;
}
else
{
millisecDifference = (curMicroseconds.lo - spriteWorldP->lastMicroseconds.lo)/1000;
}
if ( millisecDifference > 0 )
{
spriteWorldP->runningTimeCount += millisecDifference;
spriteWorldP->lastMicroseconds.lo = curMicroseconds.lo;
spriteWorldP->lastMicroseconds.hi = curMicroseconds.hi;
}
if ( (spriteWorldP->runningTimeCount - spriteWorldP->timeOfLastFrame >=
spriteWorldP->fpsTimeInterval) )
{
spriteWorldP->frameHasOccurred = true;
spriteWorldP->timeOfLastFrame = spriteWorldP->runningTimeCount;
}
else
{
spriteWorldP->frameHasOccurred = false;
return;
}
if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
{
SWFindSpritesToBeRemoved( spriteWorldP );
}
// Call the tileChangeProc, if there is one
if (spriteWorldP->tileChangeProc != NULL)
{
(*spriteWorldP->tileChangeProc)(spriteWorldP);
}
curSpriteLayerP = spriteWorldP->headSpriteLayerP;
// iterate through the layers in this world
while (curSpriteLayerP != NULL)
{
if (!curSpriteLayerP->isPaused)
{
curSpriteP = curSpriteLayerP->headSpriteP;
// iterate through the sprites in this layer
while (curSpriteP != NULL)
{
SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
nextSpriteP = curSpriteP->nextSpriteP;
// is it time to advance the sprite’s frame?
if ( curSpriteP->frameTimeInterval >= 0 &&
(spriteWorldP->runningTimeCount - curSpriteP->timeOfLastFrameChange >
curSpriteP->frameTimeInterval) )
{
register long currentFrameIndex;
curSpriteP->timeOfLastFrameChange = spriteWorldP->runningTimeCount;
currentFrameIndex = curSpriteP->curFrameIndex;
currentFrameIndex += curSpriteP->frameAdvance;
if (currentFrameIndex < curSpriteP->firstFrameIndex)
{
if (curSpriteP->frameAdvanceMode == kSWWrapAroundMode)
{
// wrap to the last frame
currentFrameIndex = curSpriteP->lastFrameIndex;
}
else // curSpriteP->frameAdvanceMode == kSWPatrollingMode
{
// change direction and set index to what it should be
curSpriteP->frameAdvance = -curSpriteP->frameAdvance;
currentFrameIndex += curSpriteP->frameAdvance;
currentFrameIndex += curSpriteP->frameAdvance;
}
}
else if (currentFrameIndex > curSpriteP->lastFrameIndex)
{
if (curSpriteP->frameAdvanceMode == kSWWrapAroundMode)
{
// wrap to the first frame
currentFrameIndex = curSpriteP->firstFrameIndex;
}
else // curSpriteP->frameAdvanceMode == kSWPatrollingMode
{
// change direction and set index to what it should be
curSpriteP->frameAdvance = -curSpriteP->frameAdvance;
currentFrameIndex += curSpriteP->frameAdvance;
currentFrameIndex += curSpriteP->frameAdvance;
}
}
curSpriteP->curFrameIndex = currentFrameIndex;
// is there a frame callback?
if (curSpriteP->frameChangeProc != NULL)
{
// get new frame
newFrameP = curSpriteP->frameArray[currentFrameIndex];
// call it
(*curSpriteP->frameChangeProc)(curSpriteP, newFrameP,
&curSpriteP->curFrameIndex);
// make sure the new frame index is in range
if (curSpriteP->curFrameIndex < 0)
{
curSpriteP->curFrameIndex = 0;
}
else if (curSpriteP->curFrameIndex >= curSpriteP->maxFrames)
{
curSpriteP->curFrameIndex = curSpriteP->maxFrames - 1;
}
}
// change the frame
newFrameP = curSpriteP->frameArray[curSpriteP->curFrameIndex];
// has the frame actually changed?
if (curSpriteP->curFrameP != newFrameP)
{
SWSetCurrentFrameIndex(curSpriteP, curSpriteP->curFrameIndex);
}
}
// is it time to move the sprite?
if ( curSpriteP->moveTimeInterval >= 0 &&
(spriteWorldP->runningTimeCount - curSpriteP->timeOfLastMove) >
curSpriteP->moveTimeInterval )
{
curSpriteP->timeOfLastMove = spriteWorldP->runningTimeCount;
// is there a movement callback?
if (curSpriteP->spriteMoveProc != NULL)
{
(*curSpriteP->spriteMoveProc)(curSpriteP);
}
}
curSpriteP = nextSpriteP;
}
}
curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
}
}
///--------------------------------------------------------------------------------------
// SWAnimateSpriteWorld
///--------------------------------------------------------------------------------------
SW_FUNC void SWAnimateSpriteWorld(
SpriteWorldPtr spriteWorldP)
{
UpdateRectStructPtr curRectStructP,
nextRectStructP;
register SpriteLayerPtr curSpriteLayerP;
register SpritePtr curSpriteP;
SpritePtr headActiveSpriteP = NULL; // Tail of active sprite list
SpritePtr headIdleSpriteP = NULL; // Tail of idle sprite list
SpritePtr curActiveSpriteP = NULL;
SpritePtr curIdleSpriteP = NULL;
Rect screenDestRect;
Rect *changedRectP;
short index, curTileLayer;
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
if (!spriteWorldP->frameHasOccurred)
return;
// Add the deadSpriteLayer if there are any Sprites in it.
if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
{
SWAddSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
}
// the current port should be the one in which we are drawing
SetGWorld(spriteWorldP->workFrameP->framePort, nil);
//-----------------erase the sprites--------------------
curSpriteLayerP = spriteWorldP->headSpriteLayerP;
curTileLayer = 0;
// iterate through the layers in this world
while (curSpriteLayerP != NULL)
{
curSpriteP = curSpriteLayerP->headSpriteP;
if (curSpriteLayerP->tileLayer > curTileLayer)
curTileLayer = curSpriteLayerP->tileLayer;
// iterate through the sprites in this layer
while (curSpriteP != NULL)
{
SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
curSpriteP->tileDepth = curTileLayer;
if ((curSpriteP->needsToBeDrawn && curSpriteP->isVisible) ||
(curSpriteP->needsToBeErased && !curSpriteP->isVisible))
{
// Add sprite to active sprite list
if (headActiveSpriteP == NULL)
headActiveSpriteP = curSpriteP;
if (curActiveSpriteP != NULL)
curActiveSpriteP->nextActiveSpriteP = curSpriteP;
curActiveSpriteP = curSpriteP;
// union last rect and current rect
// this way is much faster than UnionRect
curSpriteP->deltaFrameRect.top =
SW_MIN(curSpriteP->oldFrameRect.top, curSpriteP->destFrameRect.top);
curSpriteP->deltaFrameRect.left =
SW_MIN(curSpriteP->oldFrameRect.left, curSpriteP->destFrameRect.left);
curSpriteP->deltaFrameRect.bottom =
SW_MAX(curSpriteP->oldFrameRect.bottom, curSpriteP->destFrameRect.bottom);
curSpriteP->deltaFrameRect.right =
SW_MAX(curSpriteP->oldFrameRect.right, curSpriteP->destFrameRect.right);
{
short temp;
// align the left edge to long word boundary
curSpriteP->deltaFrameRect.left &=
(spriteWorldP->workFrameP->leftAlignFactor);
// align the right edge to long word boundary
temp = curSpriteP->deltaFrameRect.right &
spriteWorldP->workFrameP->rightAlignFactor;
if (temp != 0)
{
curSpriteP->deltaFrameRect.right +=
(spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
}
// align the left edge to long word boundary
curSpriteP->oldFrameRect.left &=
(spriteWorldP->workFrameP->leftAlignFactor);
// align the right edge to long word boundary
temp = curSpriteP->oldFrameRect.right &
spriteWorldP->workFrameP->rightAlignFactor;
if (temp != 0)
{
curSpriteP->oldFrameRect.right +=
(spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
}
}
// copy the back drop piece
(*spriteWorldP->offscreenDrawProc)(
spriteWorldP->backFrameP,
spriteWorldP->workFrameP,
&curSpriteP->oldFrameRect,
&curSpriteP->oldFrameRect);
}
else if (curSpriteP->isVisible)
{
// Add sprite to idle sprite list
if (headIdleSpriteP == NULL)
headIdleSpriteP = curSpriteP;
if (curIdleSpriteP != NULL)
curIdleSpriteP->nextIdleSpriteP = curSpriteP;
curIdleSpriteP = curSpriteP;
}
curSpriteP = curSpriteP->nextSpriteP;
}
curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
}
if (curActiveSpriteP != NULL)
curActiveSpriteP->nextActiveSpriteP = NULL;
if (curIdleSpriteP != NULL)
curIdleSpriteP->nextIdleSpriteP = NULL;
// update flagged background rects
curRectStructP = spriteWorldP->headUpdateRectP;
while ( curRectStructP != NULL )
{
(*spriteWorldP->offscreenDrawProc)(
spriteWorldP->backFrameP,
spriteWorldP->workFrameP,
&curRectStructP->updateRect,
&curRectStructP->updateRect);
curRectStructP = curRectStructP->nextRectStructP;
}
// Redraw idle sprites that were erased by a tile
if (spriteWorldP->numTilesChanged > 0)
SWCheckIdleSpritesWithTiles(spriteWorldP, headIdleSpriteP);
// Redraw idle sprites that were erased by an updateRect
if (spriteWorldP->headUpdateRectP != NULL)
SWCheckIdleSpritesWithRects(spriteWorldP, headIdleSpriteP);
// Call the postEraseCallBack
if (spriteWorldP->postEraseCallBack != NULL)
(*spriteWorldP->postEraseCallBack)(spriteWorldP);
//-----------------draw the sprites--------------------
curSpriteLayerP = spriteWorldP->headSpriteLayerP;
// iterate through the layers in this world
while (curSpriteLayerP != NULL)
{
curSpriteP = curSpriteLayerP->headSpriteP;
// iterate through the sprites in this layer
while (curSpriteP != NULL)
{
if (curSpriteP->isVisible)
{
if (curSpriteP->needsToBeDrawn)
{
gCurrentSpriteBeingDrawn = curSpriteP;
// draw the sprite in the work area
(*curSpriteP->frameDrawProc)(
curSpriteP->curFrameP,
spriteWorldP->workFrameP,
&curSpriteP->curFrameP->frameRect,
&curSpriteP->destFrameRect);
gCurrentSpriteBeingDrawn = NULL;
if (spriteWorldP->tilingIsOn &&
curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
{
screenDestRect = curSpriteP->destFrameRect;
// Clip screenDestRect to visScrollRect
if (screenDestRect.left < spriteWorldP->visScrollRect.left)
screenDestRect.left = spriteWorldP->visScrollRect.left;
if (screenDestRect.right > spriteWorldP->visScrollRect.right)
screenDestRect.right = spriteWorldP->visScrollRect.right;
if (screenDestRect.top < spriteWorldP->visScrollRect.top)
screenDestRect.top = spriteWorldP->visScrollRect.top;
if (screenDestRect.bottom > spriteWorldP->visScrollRect.bottom)
screenDestRect.bottom = spriteWorldP->visScrollRect.bottom;
SWDrawTilesAboveSprite(spriteWorldP, &screenDestRect, curSpriteP->tileDepth);
}
}
else
{
SWCheckIdleSpriteOverlap(spriteWorldP, curSpriteP, headActiveSpriteP);
}
}
curSpriteP = curSpriteP->nextSpriteP;
}
curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
}
// Call the postDrawCallBack
if (spriteWorldP->postDrawCallBack != NULL)
(*spriteWorldP->postDrawCallBack)(spriteWorldP);
//-----------------update the screen--------------------
// the current port should be the one in which we are drawing
SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
// wait for the VBL
if ( spriteWorldP->usingVBL )
{
spriteWorldP->vblTaskRec.hasVBLFired = false;
while ( !spriteWorldP->vblTaskRec.hasVBLFired )
{}
}
curSpriteP = headActiveSpriteP;
// Has a custom worldRect been used? (If so, sprites need offsetting)
if (spriteWorldP->windRect.left || spriteWorldP->windRect.top)
{
// update flagged background rects
curRectStructP = spriteWorldP->headUpdateRectP;
while ( curRectStructP != NULL )
{
screenDestRect = curRectStructP->updateRect;
screenDestRect.left += spriteWorldP->windRect.left;
screenDestRect.right += spriteWorldP->windRect.left;
screenDestRect.top += spriteWorldP->windRect.top;
screenDestRect.bottom += spriteWorldP->windRect.top;
(*spriteWorldP->screenDrawProc)(
spriteWorldP->workFrameP,
spriteWorldP->windowFrameP,
&curRectStructP->updateRect,
&screenDestRect);
curRectStructP = curRectStructP->nextRectStructP;
}
// Update on screen the tiles that have changed
changedRectP = spriteWorldP->changedTiles;
for (index = 0; index < spriteWorldP->numTilesChanged; index++, changedRectP++)
{
screenDestRect = *changedRectP;
// offset dest rect for screen
screenDestRect.left += spriteWorldP->windRect.left;
screenDestRect.right += spriteWorldP->windRect.left;
screenDestRect.top += spriteWorldP->windRect.top;
screenDestRect.bottom += spriteWorldP->windRect.top;
(*spriteWorldP->screenDrawProc)(spriteWorldP->workFrameP,
spriteWorldP->windowFrameP, changedRectP, &screenDestRect);
}
// update the sprites on the screen
while (curSpriteP != NULL)
{
// offset the sprite's delta rect for the screen
screenDestRect = curSpriteP->deltaFrameRect;
screenDestRect.left += spriteWorldP->windRect.left;
screenDestRect.right += spriteWorldP->windRect.left;
screenDestRect.top += spriteWorldP->windRect.top;
screenDestRect.bottom += spriteWorldP->windRect.top;
(*spriteWorldP->screenDrawProc)(
spriteWorldP->workFrameP,
spriteWorldP->windowFrameP,
&curSpriteP->deltaFrameRect,
&screenDestRect);
// set the delta and last rect to the current rect
curSpriteP->deltaFrameRect = curSpriteP->destFrameRect;
curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
// this sprite no longer needs to be drawn
curSpriteP->needsToBeDrawn = false;
curSpriteP->needsToBeErased = false;
curSpriteP = curSpriteP->nextActiveSpriteP;
}
}
else
{
// update flagged background rects
curRectStructP = spriteWorldP->headUpdateRectP;
while ( curRectStructP != NULL )
{
(*spriteWorldP->screenDrawProc)(
spriteWorldP->workFrameP,
spriteWorldP->windowFrameP,
&curRectStructP->updateRect,
&curRectStructP->updateRect);
curRectStructP = curRectStructP->nextRectStructP;
}
// Update on screen the tiles that have changed
changedRectP = spriteWorldP->changedTiles;
for (index = 0; index < spriteWorldP->numTilesChanged; index++, changedRectP++)
{
(*spriteWorldP->screenDrawProc)(spriteWorldP->workFrameP,
spriteWorldP->windowFrameP, changedRectP, changedRectP);
}
// update the sprites on the screen
while (curSpriteP != NULL)
{
(*spriteWorldP->screenDrawProc)(
spriteWorldP->workFrameP,
spriteWorldP->windowFrameP,
&curSpriteP->deltaFrameRect,
&curSpriteP->deltaFrameRect);
// set the delta and last rect to the current rect
curSpriteP->deltaFrameRect = curSpriteP->destFrameRect;
curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
// this sprite no longer needs to be drawn
curSpriteP->needsToBeDrawn = false;
curSpriteP->needsToBeErased = false;
curSpriteP = curSpriteP->nextActiveSpriteP;
}
}
// dispose of flagged background rects
nextRectStructP = spriteWorldP->headUpdateRectP;
while ( nextRectStructP != NULL )
{
curRectStructP = nextRectStructP;
nextRectStructP = curRectStructP->nextRectStructP;
DisposePtr( (Ptr)curRectStructP );
}
spriteWorldP->headUpdateRectP = NULL;
spriteWorldP->numTilesChanged = 0;
// Remove the deadSpriteLayer if we added it earlier.
if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
{
SWRemoveSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
}
}
///--------------------------------------------------------------------------------------
// SWCheckIdleSpriteOverlap
///--------------------------------------------------------------------------------------
SW_FUNC void SWCheckIdleSpriteOverlap(
SpriteWorldPtr spriteWorldP,
register SpritePtr idleSpriteP,
SpritePtr headActiveSpriteP)
{
register SpritePtr activeSpriteP = headActiveSpriteP;
Rect srcSectRect, dstSectRect;
// iterate through the active sprites
while (activeSpriteP != NULL)
{
// do the sprites overlap?
if ((idleSpriteP->oldFrameRect.top < activeSpriteP->deltaFrameRect.bottom) &&
(idleSpriteP->oldFrameRect.bottom > activeSpriteP->deltaFrameRect.top) &&
(idleSpriteP->oldFrameRect.left < activeSpriteP->deltaFrameRect.right) &&
(idleSpriteP->oldFrameRect.right > activeSpriteP->deltaFrameRect.left))
{
// calculate the intersection between the idle sprite's destination
// rect, and the active sprite's delta rect
dstSectRect.left =
SW_MAX(idleSpriteP->destFrameRect.left, activeSpriteP->deltaFrameRect.left);
dstSectRect.top =
SW_MAX(idleSpriteP->destFrameRect.top, activeSpriteP->deltaFrameRect.top);
dstSectRect.right =
SW_MIN(idleSpriteP->destFrameRect.right, activeSpriteP->deltaFrameRect.right);
dstSectRect.bottom =
SW_MIN(idleSpriteP->destFrameRect.bottom, activeSpriteP->deltaFrameRect.bottom);
srcSectRect = idleSpriteP->curFrameP->frameRect;
srcSectRect.left += (dstSectRect.left - idleSpriteP->destFrameRect.left);
srcSectRect.top += (dstSectRect.top - idleSpriteP->destFrameRect.top);
srcSectRect.right -= (idleSpriteP->destFrameRect.right - dstSectRect.right);
srcSectRect.bottom -= (idleSpriteP->destFrameRect.bottom - dstSectRect.bottom);
// copy a piece of the sprite image onto the workFrame
gCurrentSpriteBeingDrawn = idleSpriteP;
(*idleSpriteP->frameDrawProc)(
idleSpriteP->curFrameP,
spriteWorldP->workFrameP,
&srcSectRect,
&dstSectRect);
gCurrentSpriteBeingDrawn = NULL;
if (spriteWorldP->tilingIsOn &&
idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
{
// Clip dstSectRect to visScrollRect
if (dstSectRect.left < spriteWorldP->visScrollRect.left)
dstSectRect.left = spriteWorldP->visScrollRect.left;
if (dstSectRect.right > spriteWorldP->visScrollRect.right)
dstSectRect.right = spriteWorldP->visScrollRect.right;
if (dstSectRect.top < spriteWorldP->visScrollRect.top)
dstSectRect.top = spriteWorldP->visScrollRect.top;
if (dstSectRect.bottom > spriteWorldP->visScrollRect.bottom)
dstSectRect.bottom = spriteWorldP->visScrollRect.bottom;
SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
}
}
activeSpriteP = activeSpriteP->nextActiveSpriteP;
}
}
///--------------------------------------------------------------------------------------
// SWCheckIdleSpritesWithTiles - redraw sprites erased by tiles that changed
///--------------------------------------------------------------------------------------
SW_FUNC void SWCheckIdleSpritesWithTiles(
SpriteWorldPtr spriteWorldP,
SpritePtr headIdleSpriteP)
{
Rect srcSectRect, dstSectRect;
register SpritePtr idleSpriteP;
short srcHorizOffset;
short srcVertOffset;
Rect *changedRectP;
short index;
// Cycle through the changedTiles array of rects
changedRectP = spriteWorldP->changedTiles;
for (index = 0; index < spriteWorldP->numTilesChanged; index++, changedRectP++)
{
idleSpriteP = headIdleSpriteP;
// iterate through the idle sprites
while (idleSpriteP != NULL)
{
// does the idle sprite overlap the changedRect?
if ((idleSpriteP->oldFrameRect.top < changedRectP->bottom) &&
(idleSpriteP->oldFrameRect.bottom > changedRectP->top) &&
(idleSpriteP->oldFrameRect.left < changedRectP->right) &&
(idleSpriteP->oldFrameRect.right > changedRectP->left))
{
// calculate the intersection between the idle
// sprite's rect and the changedRectP
dstSectRect.left =
SW_MAX(idleSpriteP->oldFrameRect.left, changedRectP->left);
dstSectRect.top =
SW_MAX(idleSpriteP->oldFrameRect.top, changedRectP->top);
dstSectRect.right =
SW_MIN(idleSpriteP->oldFrameRect.right, changedRectP->right);
dstSectRect.bottom =
SW_MIN(idleSpriteP->oldFrameRect.bottom, changedRectP->bottom);
// Calculate the source rect
srcSectRect = dstSectRect;
srcHorizOffset = idleSpriteP->curFrameP->frameRect.left;
srcVertOffset = idleSpriteP->curFrameP->frameRect.top;
srcSectRect.left -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
srcSectRect.right -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
srcSectRect.top -= (idleSpriteP->oldFrameRect.top - srcVertOffset);
srcSectRect.bottom -= (idleSpriteP->oldFrameRect.top - srcVertOffset);
// Copy a piece of the sprite image onto the back drop piece
gCurrentSpriteBeingDrawn = idleSpriteP;
(*idleSpriteP->frameDrawProc)(
idleSpriteP->curFrameP,
spriteWorldP->workFrameP,
&srcSectRect,
&dstSectRect);
gCurrentSpriteBeingDrawn = NULL;
if (spriteWorldP->tilingIsOn &&
idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
{
dstSectRect.top += spriteWorldP->vertScrollRectOffset;
dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
dstSectRect.left += spriteWorldP->horizScrollRectOffset;
dstSectRect.right += spriteWorldP->horizScrollRectOffset;
SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
}
}
idleSpriteP = idleSpriteP->nextIdleSpriteP;
}
}
}
///--------------------------------------------------------------------------------------
// SWCheckIdleSpritesWithRects - redraw sprites erased by updateRects
///--------------------------------------------------------------------------------------
SW_FUNC void SWCheckIdleSpritesWithRects(
SpriteWorldPtr spriteWorldP,
SpritePtr headIdleSpriteP)
{
UpdateRectStructPtr curRectStructP;
register SpritePtr idleSpriteP;
Rect srcSectRect, dstSectRect;
short srcHorizOffset;
short srcVertOffset;
Rect *changedRectP;
curRectStructP = spriteWorldP->headUpdateRectP;
while (curRectStructP != NULL)
{
changedRectP = &curRectStructP->updateRect;
idleSpriteP = headIdleSpriteP;
// iterate through the idle sprites
while (idleSpriteP != NULL)
{
// does the idle sprite overlap the changedRect?
if ((idleSpriteP->oldFrameRect.top < changedRectP->bottom) &&
(idleSpriteP->oldFrameRect.bottom > changedRectP->top) &&
(idleSpriteP->oldFrameRect.left < changedRectP->right) &&
(idleSpriteP->oldFrameRect.right > changedRectP->left))
{
// calculate the intersection between the idle
// sprite's rect and the changedRectP
dstSectRect.left =
SW_MAX(idleSpriteP->oldFrameRect.left, changedRectP->left);
dstSectRect.top =
SW_MAX(idleSpriteP->oldFrameRect.top, changedRectP->top);
dstSectRect.right =
SW_MIN(idleSpriteP->oldFrameRect.right, changedRectP->right);
dstSectRect.bottom =
SW_MIN(idleSpriteP->oldFrameRect.bottom, changedRectP->bottom);
// Calculate the source rect
srcSectRect = dstSectRect;
srcHorizOffset = idleSpriteP->curFrameP->frameRect.left;
srcVertOffset = idleSpriteP->curFrameP->frameRect.top;
srcSectRect.left -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
srcSectRect.right -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
srcSectRect.top -= (idleSpriteP->oldFrameRect.top - srcVertOffset);
srcSectRect.bottom -= (idleSpriteP->oldFrameRect.top - srcVertOffset);
// Copy a piece of the sprite image onto the back drop piece
gCurrentSpriteBeingDrawn = idleSpriteP;
(*idleSpriteP->frameDrawProc)(
idleSpriteP->curFrameP,
spriteWorldP->workFrameP,
&srcSectRect,
&dstSectRect);
gCurrentSpriteBeingDrawn = NULL;
if (spriteWorldP->tilingIsOn &&
idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
{
dstSectRect.top += spriteWorldP->vertScrollRectOffset;
dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
dstSectRect.left += spriteWorldP->horizScrollRectOffset;
dstSectRect.right += spriteWorldP->horizScrollRectOffset;
SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
}
}
idleSpriteP = idleSpriteP->nextIdleSpriteP;
}
curRectStructP = curRectStructP->nextRectStructP;
}
}
///--------------------------------------------------------------------------------------
// SWFindSpritesToBeRemoved
///--------------------------------------------------------------------------------------
SW_FUNC void SWFindSpritesToBeRemoved(
SpriteWorldPtr spriteWorldP )
{
SpritePtr curSpriteP, nextSpriteP;
curSpriteP = spriteWorldP->deadSpriteLayerP->headSpriteP;
// iterate through the sprites in the deadSpriteLayerP
while (curSpriteP != NULL)
{
nextSpriteP = curSpriteP->nextSpriteP;
// all the Sprites here should need removing...
SW_ASSERT(curSpriteP->spriteRemoval != kSWDontRemoveSprite);
// has this sprite been erased by SWAnimate?
if (curSpriteP->needsToBeErased == false)
{
// if so, we can safely remove it from its layer
SWRemoveSprite(curSpriteP);
// do we want to dispose of this sprite too?
if (curSpriteP->spriteRemoval == kSWRemoveAndDisposeSprite)
SWDisposeSprite(&curSpriteP);
else
curSpriteP->spriteRemoval = kSWDontRemoveSprite; // We're done
}
curSpriteP = nextSpriteP;
}
}
///--------------------------------------------------------------------------------------
// SWFlagRectAsChanged
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWFlagRectAsChanged(
SpriteWorldPtr spriteWorldP,
Rect* theChangedRect)
{
UpdateRectStructPtr curRectStructP,
newUpdateRectP;
short temp;
OSErr err = noErr;
// align the left edge to long word boundary
theChangedRect->left &= (spriteWorldP->workFrameP->leftAlignFactor);
// align the right edge to long word boundary
temp = theChangedRect->right & spriteWorldP->workFrameP->rightAlignFactor;
if (temp != 0)
{
theChangedRect->right += (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
}
newUpdateRectP = (UpdateRectStructPtr)NewPtr(sizeof(UpdateRectStruct));
if ( newUpdateRectP != NULL )
{
newUpdateRectP->updateRect = *theChangedRect;
newUpdateRectP->nextRectStructP = NULL;
if ( spriteWorldP->headUpdateRectP == NULL )
{
spriteWorldP->headUpdateRectP = newUpdateRectP;
}
else
{
curRectStructP = spriteWorldP->headUpdateRectP;
while ( curRectStructP->nextRectStructP != NULL )
{
curRectStructP = curRectStructP->nextRectStructP;
}
curRectStructP->nextRectStructP = newUpdateRectP;
}
}
else
{
err = MemError();
}
return err;
}
///--------------------------------------------------------------------------------------
// SWFlagScrollingRectAsChanged - same as SWFlagRectAsChanged, minus alignment code
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWFlagScrollingRectAsChanged(
SpriteWorldPtr spriteWorldP,
Rect* theChangedRect)
{
UpdateRectStructPtr curRectStructP,
newUpdateRectP;
OSErr err = noErr;
newUpdateRectP = (UpdateRectStructPtr)NewPtr(sizeof(UpdateRectStruct));
if ( newUpdateRectP != NULL )
{
newUpdateRectP->updateRect = *theChangedRect;
newUpdateRectP->nextRectStructP = NULL;
if ( spriteWorldP->headUpdateRectP == NULL )
{
spriteWorldP->headUpdateRectP = newUpdateRectP;
}
else
{
curRectStructP = spriteWorldP->headUpdateRectP;
while ( curRectStructP->nextRectStructP != NULL )
{
curRectStructP = curRectStructP->nextRectStructP;
}
curRectStructP->nextRectStructP = newUpdateRectP;
}
}
else
{
err = MemError();
}
return err;
}
///--------------------------------------------------------------------------------------
// SWSetSpriteWorldMaxFPS
///--------------------------------------------------------------------------------------
SW_FUNC void SWSetSpriteWorldMaxFPS(
SpriteWorldPtr spriteWorldP,
short framesPerSec)
{
SW_ASSERT(spriteWorldP != NULL);
// is framesPerSec a valid value?
if (framesPerSec > 0 && framesPerSec <= 1000 )
{
spriteWorldP->fpsTimeInterval = 1000/framesPerSec;
}
// framesPerSec is an "ignore it" value.
else
{
spriteWorldP->fpsTimeInterval = 0;
}
}
///--------------------------------------------------------------------------------------
// SWSyncSpriteWorldToVBL
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWSyncSpriteWorldToVBL(
SpriteWorldPtr spriteWorldP,
Boolean syncingOn)
{
OSErr err = noErr;
AuxDCEHandle mainDCE;
SW_ASSERT(spriteWorldP != NULL);
if ( syncingOn )
{
if ( !spriteWorldP->usingVBL )
{
*((VBLUPP*)&spriteWorldP->vblTaskRec.myVBLTask.vblAddr) =
NewVBLProc((ProcPtr)SWVBLTask);
spriteWorldP->vblTaskRec.myVBLTask.qType = vType;
spriteWorldP->vblTaskRec.myVBLTask.vblCount = 1;
spriteWorldP->vblTaskRec.hasVBLFired = false;
// insert the task into the VBL queue
mainDCE = (AuxDCEHandle)GetDCtlEntry((**spriteWorldP->mainSWGDH).gdRefNum);
err = SlotVInstall( (QElemPtr) &spriteWorldP->vblTaskRec.myVBLTask,
(**mainDCE).dCtlSlot );
if ( err == noErr )
{
spriteWorldP->usingVBL = true;
}
}
}
else
{
if ( spriteWorldP->usingVBL )
{
mainDCE = (AuxDCEHandle)GetDCtlEntry((**spriteWorldP->mainSWGDH).gdRefNum);
err = SlotVRemove( (QElemPtr) &spriteWorldP->vblTaskRec.myVBLTask,
(**mainDCE).dCtlSlot );
spriteWorldP->vblTaskRec.hasVBLFired = true;
spriteWorldP->usingVBL = false;
DisposeRoutineDescriptor(spriteWorldP->vblTaskRec.myVBLTask.vblAddr);
}
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWVBLTask
///--------------------------------------------------------------------------------------
#if !GENERATINGCFM
extern VBLTaskRecPtr GetVBLRec(void)
= 0x2008; /* MOVE.L A0,D0 */
#endif
#if GENERATINGCFM
void SWVBLTask(VBLTaskRecPtr vblTaskPtr)
{
vblTaskPtr->hasVBLFired = true;
// Reset vblCount so that this procedure executes again
vblTaskPtr->myVBLTask.vblCount = 1;
}
#else
void SWVBLTask( void )
{
VBLTaskRecPtr vblTaskPtr;
vblTaskPtr = (VBLTaskRecPtr) GetVBLRec();
vblTaskPtr->hasVBLFired = true;
// Reset vblCount so that this procedure executes again
vblTaskPtr->myVBLTask.vblCount = 1;
}
#endif
///--------------------------------------------------------------------------------------
// SWSetCleanUpSpriteWorld - call this if you want FatalError() or SWAssertFail() to call
// SWSyncSpriteWorldToVBL with a value of false for your SpriteWorld before it calls
// ExitToShell. You pass a pointer to the SpriteWorld you want to be "cleaned up".
///--------------------------------------------------------------------------------------
void SWSetCleanUpSpriteWorld(SpriteWorldPtr spriteWorldP)
{
gCleanUpSpriteWorldP = spriteWorldP;
}
///--------------------------------------------------------------------------------------
// SWGetSpriteWorldVersion
///--------------------------------------------------------------------------------------
SW_FUNC unsigned long SWGetSpriteWorldVersion(void)
{
return 0x02210000;
}